<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // ==========================================================================
    // Iterator
    // function myIterator(arr) {
    //     var index = 0
    //     return {
    //         next() {
    //             return index !== arr.length ?
    //                 { value: arr[index++], done: false } :
    //                 { value: undefined, done: true }

    //         }
    //     }
    // }

    // var m = myIterator(['a', 'b', 'c', 'd', 'e']);
    // console.log(m.next());//{value: 'a', done: false}
    // console.log(m.next());//{value: 'b', done: false}
    // console.log(m.next());//{value: 'c', done: false}
    // console.log(m.next());//{value: 'd', done: false}
    // console.log(m.next());//{value: 'e', done: false}
    // console.log(m.next());//{value: undefined, done: true}



    // 使用数组迭代器(数组自带的)
    // var  arr =[1,2,3]
    // console.log(arr);
    // var it =arr[Symbol.iterator]()
    // console.log(it.next());//{value: 1, done: false}
    // console.log(it.next());//{value: 2, done: false}
    // console.log(it.next());//{value: 3, done: false}
    // console.log(it.next());//{value: undefined, done: true}


    // 调用Iterator接口的场合
    // var set = new Set().add('j').add('a').add('y')
    // var [a, ...b] = set;
    // console.log(a, b);//j    ['a', 'y']
    // var [a, b] = set;
    // console.log(a, b);//j a


    // ==========================================================================
    // for...of...
    // // 数组
    // // 本身部署了Iterator接口，可以直接遍历
    // var arr = [1, 2, 3, 4];
    // for (const value of arr) {
    //     console.log(value);
    // }

    // // 对象
    // // 对象本身没有部署Iterator这个接口，无法直接遍历，可以使用Object.entries()方法
    // var obj = {
    //     name: 'jay',
    //     age: 18,
    //     sex: 'man'
    // }
    // for (const [key, value] of Object.entries(obj)) {
    //     console.log(key, value);
    // }

    // // 字符串
    // // 可以看做为一个伪数组，也有Iterator接口，可以直接遍历
    // var str = 'hi boy'
    // for (const value of str) {
    //     console.log(value);
    // }



    // --------------------------------------------------------------------------------------
    // for...of...遍历Iterator数据
    // function myIterator(arr) {
    //     var index = 0;
    //     // 要使一个对象可迭代，它需要实现迭代器协议，这个协议包括一个 [Symbol.iterator] 方法，这个方法返回一个迭代器对象
    //     return {
    //         // 实现迭代器协议的 [Symbol.iterator] 方法
    //         [Symbol.iterator]: function () {
    //             // 返回迭代器对象本身
    //             return this;
    //         },
    //         next() {
    //             return index !== arr.length ?
    //                 { value: arr[index++], done: false } :
    //                 { value: undefined, done: true }
    //         }
    //     }
    // }
    // var m = myIterator(['a', 'b', 'c', 'd', 'e']);
    // for (const value of m) {
    //     console.log(value);
    // }


    // --------------------------------------------------------------------------------------
    // for...of...遍历Map数据
    // var mp = new Map([
    //     ['one:', 1],
    //     // 将函数作为一个值
    //     ['two:', (() => { const num = 2; return num; })()],
    //     // 将对象作为一个值
    //     ['three:', { four: 3 }],
    //     // 将嵌套数组作为一个值
    //     ['five', [5, ['五']]]
    // ]);
    // for (const [key, value] of mp) {
    //     console.log(key, value);
    // }



    // --------------------------------------------------------------------------------------
    // for...of...遍历Set数据
    // var st = new Set().add('a').add('b').add('c').add('d').add('e').add('e').add('e').add('f');
    // var s = new Set([1, 2, 3, 4, 1, 6, 5, 2, 1, 4, 3, 2, 1])
    // for (const value of st) {
    //     console.log(value);
    // }
    // for (const value of s) {
    //     console.log(value);
    // }
    // ==========================================================================
    // Generator 生成器/状态机
    // 异步编程的解决方案，可以实现函数的懒执行，中途暂停

    // 函数使用*标记为一个生成器
    // 内部使用yield产生的一个状态
    // 在函数外部调用生成器函数使用next方法，如果没有传参，那么函数内部指定位置的yield返回值是undefined
    // function* fn() {
    //     // 暂停
    //     var a = yield 1;
    //     console.log(a);//20  返回值是undefined
    //     var b = yield 2;
    //     console.log(b);//30  返回值是undefined
    //     var c = yield 3;
    //     console.log(c);//40  返回值是undefined
    //     return a + b + c;
    // }
    // var f = fn();
    // console.log(f.next(10));//{value: 1, done: false}
    // console.log(f.next(20));//{value: 2, done: false}
    // console.log(f.next(30));//{value: 3, done: false}
    // // console.log(f.next());//{value: NaN, done: true}
    // console.log(f.next(40));//{value: 90, done: true}



    // --------------------------------------------------------------------------------------
    // 与Iterator接口的关系
    // var obj = {}
    // obj[Symbol.iterator] = function* () {
    //     yield 1;
    //     yield 2;
    //     yield 3;
    //     return 4;
    // }
    // console.log([...obj]);


    // --------------------------------------------------------------------------------------
    // next，throw，return



    // next方法的参数
    // 作为上一个yield的返回值，如果没有传参，默认返回undefined
    // function* f() {
    //     for (var i = 0; true; i++) {
    //         var rest = yield i;
    //         if (rest) { i = -1; }
    //     }
    // }
    // var g = f();
    // console.log(g.next());//0
    // console.log(g.next());//1
    // console.log(g.next());//2
    // console.log(g.next());//3
    // console.log(g.next(true));//0
    // console.log(g.next());//1
    // console.log(g.next());//2
    // console.log(g.next());//3
    // for(const a of f()){
    //     // 死循环
    //     console.log(a);
    // }

    

    // // 错误throw
    // function* f(a,b){
    //     var res =yield a +b ;
    //     return res;
    // }
    // var g =f(1,2);
    // console.log(g.next());//3
    // console.log(g.next(5));//5
    // g.throw(new Error('发生错误！！！'))


    // --------------------------------------------------------------------------------------
    // 函数的*还可以写在哪里
    // // 类
    // class MyClass {
    //     *f() {
    //         for (var i = 0; true; i++) {
    //             var rest = yield i;
    //             if (rest) { i = -1; }
    //         }

    //     }
    // }
    // // 创建 MyClass 的实例
    // const m = new MyClass();
    // // 获取生成器函数的迭代器
    // const g = m.f();
    // // 调用生成器函数的 next 方法来遍历
    // console.log(g.next()); //  0
    // console.log(g.next()); //  1
    // console.log(g.next(true)); //  0
    // console.log(g.next()); //  1

    // 对象
    // var obj = {
    //     *f() {
    //         for (var i = 0; true; i++) {
    //             var rest = yield i;
    //             if (rest) { i = -1; }
    //         }
    //     }
    // };
    // var o =obj.f();
    // console.log(o.next());//0
    // console.log(o.next());//1
    // console.log(o.next());//2
    // console.log(o.next(true));//0
    // console.log(o.next());//1
    // console.log(o.next());//2



    // ==========================================================================
    // 异步应用
    














</script>


</html>